home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1999 July: Technology Seed / ADC Seed CD - July 1999.toast / USB / Mac OS USB DDK v1.2 / Examples / UniversalModule / UniversalModule.c < prev    next >
Encoding:
C/C++ Source or Header  |  1999-04-15  |  15.2 KB  |  425 lines  |  [TEXT/MPS ]

  1. /*
  2.     File:        UniversalModule.c
  3.  
  4.     Contains:    HID Module for USB Universal
  5.  
  6.     Version:    xxx put version here xxx
  7.  
  8.     Copyright:    © 1997-1998 by Apple Computer, Inc., all rights reserved.
  9.  
  10. */
  11.  
  12. #include <Types.h>
  13. #include <Devices.h>
  14. #include <processes.h>
  15. #include <DriverServices.h>
  16.  
  17. #include <USB.h>
  18.  
  19. #include "UniversalModule.h"
  20.  
  21. usbUniversalPBStruct myUniversalPB;
  22.  
  23.  
  24. void SetParamBlock(USBInterfaceRef theInterfaceRef, USBPB * paramblock);
  25. Boolean immediateError(OSStatus err);
  26.  
  27. void SetParamBlock(USBInterfaceRef theInterfaceRef, USBPB * paramblock)
  28. {
  29.     paramblock->pbVersion = kUSBCurrentPBVersion;
  30.     paramblock->pbLength = sizeof(usbUniversalPBStruct);
  31.  
  32.     paramblock->usbReference = theInterfaceRef;
  33.  
  34.     paramblock->usb.cntl.WValue = 0;
  35.     paramblock->usb.cntl.WIndex = 0;             
  36.     paramblock->usbBuffer = nil;        
  37.     paramblock->usbReqCount = 0;
  38.     paramblock->usbClassType = 0;
  39.     paramblock->usbSubclass = 0;
  40.     paramblock->usbFlags = 0;
  41.     paramblock->usbOther = 0;
  42.  
  43.     paramblock->usbStatus = noErr;
  44.  
  45.     paramblock->usbCompletion = (USBCompletion) TransactionCompletionProc;
  46. }
  47.  
  48. Boolean immediateError(OSStatus err)
  49. {
  50.     return((err != kUSBPending) && (err != noErr) );
  51. }
  52.  
  53. void UniversalModuleInitiateTransaction(USBPB *pb)
  54. {
  55. register usbUniversalPBStruct *pUniversalPB;
  56. OSStatus myErr;
  57. UInt32    size;
  58. UInt32    count;
  59. USBHIDReportDesc * currentDesc;
  60. usbHIDDescriptorInfo * currentOwnedDesc;
  61.  
  62.     pUniversalPB = (usbUniversalPBStruct *)(pb);
  63.     pUniversalPB->transDepth++;
  64.     if (pUniversalPB->transDepth < 0)
  65.     {
  66.         USBExpertFatalError(pUniversalPB->interfaceRef, kUSBInternalErr, "\pUSBUniversalModule: transDepth < 0 (initiation)", pUniversalPB->transDepth );
  67.     }
  68.     
  69.     if (pUniversalPB->transDepth > 1)
  70.     {
  71.         USBExpertFatalError(pUniversalPB->interfaceRef, kUSBInternalErr, "\pUSBUniversalModule: transDepth > 1 (initiation)", pUniversalPB->transDepth );
  72.     }
  73.     
  74.     switch(pUniversalPB->pb.usbRefcon & ~kRetryTransaction)
  75.     {
  76.         case kGetHIDDesc:
  77.             pUniversalPB->pb.usb.cntl.WIndex = 0;
  78.             pUniversalPB->pb.usbBuffer = &pUniversalPB->hidDiscriptor;
  79.             pUniversalPB->pb.usbReqCount = sizeof (pUniversalPB->hidDiscriptor);
  80.             pUniversalPB->pb.usbOther = kUSBHIDDesc;
  81.             
  82.             pUniversalPB->pb.usbRefcon |= kCompletionPending;
  83.             myErr = USBFindNextAssociatedDescriptor(&pUniversalPB->pb);
  84.             if(immediateError(myErr))
  85.             {
  86.                 USBExpertFatalError(pUniversalPB->interfaceRef, kUSBInternalErr, "\pUSBUniversalModule: kGetHIDDesc (ImmediateError)", myErr);
  87.             }
  88.             break;
  89.  
  90.         case kAllocHIDOwnedDescMem:
  91.             // we will allocate 1 block to hold all the hid descriptor stuff:
  92.             // first an array of 'usbHIDDescriptorInfo' containing type, length, and ptrs to the data later in the block
  93.             // then the actual descriptors, which will be pointed by the usbHIDDescriptorInfo array
  94.             
  95.             count = pUniversalPB->hidDiscriptor.d.hidNumDescriptors;
  96.             size = count * sizeof (usbHIDDescriptorInfo);    // inital part for the array
  97.             
  98.             // now add for each descriptor
  99.             currentDesc = (USBHIDReportDesc *) &pUniversalPB->hidDiscriptor.d.hidDescriptorType;
  100.             while (count--)
  101.             {
  102.                 size += (currentDesc->hidDescriptorLengthHi << 8) + currentDesc->hidDescriptorLengthLo;
  103.                 ;
  104.                 currentDesc = (USBHIDReportDesc *) (((UInt8 *) currentDesc) + 3);    // make _sure_ we add 3 bytes not 4 regardless of struct alignment
  105.             }
  106.             
  107.             // now ask usbserviceslib to allocate the memory
  108.             pUniversalPB->pb.usbReqCount = pUniversalPB->allocatedBufferSize = size;
  109.             pUniversalPB->pb.usbFlags = 0;
  110.         
  111.             pUniversalPB->pb.usbRefcon |= kCompletionPending;
  112.             myErr = USBAllocMem(&pUniversalPB->pb);
  113.             if(immediateError(myErr))
  114.             {
  115.                 USBExpertFatalError(pUniversalPB->interfaceRef, kUSBInternalErr, "\pUSBUniversalModule: kAllocHIDOwnedDescMem (ImmediateError)", myErr);
  116.             }
  117.             break;
  118.  
  119.         case kGet1OwnedHIDDesc:
  120.             // hidOwnedDescriptorsCount is the number of owned decriptors we have successfully fetched
  121.             currentOwnedDesc = &pUniversalPB->hidOwnedDiscriptors[pUniversalPB->hidOwnedDescriptorsCount];
  122.             
  123.             SetParamBlock(pUniversalPB->interfaceRef, &pUniversalPB->pb);
  124.             pUniversalPB->pb.usb.cntl.BMRequestType = USBMakeBMRequestType(kUSBIn, kUSBStandard, kUSBInterface); // 10000001
  125.             pUniversalPB->pb.usb.cntl.BRequest = kUSBRqGetDescriptor;
  126.             pUniversalPB->pb.usb.cntl.WValue = (currentOwnedDesc->type << 8) + currentOwnedDesc->typeIndex;     // type and index
  127.             pUniversalPB->pb.usb.cntl.WIndex = pUniversalPB->interfaceNum;                                    // interface number
  128.             pUniversalPB->pb.usbReqCount = currentOwnedDesc->length;
  129.             pUniversalPB->pb.usbBuffer = currentOwnedDesc->descriptor;
  130.  
  131.             pUniversalPB->pb.usbRefcon |= kCompletionPending;
  132.             myErr = USBDeviceRequest(&pUniversalPB->pb);
  133.             if(immediateError(myErr))
  134.             {
  135.                 USBExpertFatalError(pUniversalPB->interfaceRef, kUSBInternalErr, "\pUSBUniversalModule: kGet1OwnedHIDDesc (ImmediateError)", myErr);
  136.             }
  137.             break;
  138.  
  139.         case kConfigureInterface:
  140.             SetParamBlock(pUniversalPB->interfaceRef, &pUniversalPB->pb);
  141.             
  142.             pUniversalPB->pb.usbRefcon |= kCompletionPending;
  143.             pUniversalPB->pb.usbBuffer = 0;
  144.             pUniversalPB->pb.usbReqCount = 0;
  145.             pUniversalPB->pb.usbActCount = 0;
  146.             
  147.             myErr = USBConfigureInterface(&pUniversalPB->pb);
  148.             if(immediateError(myErr))
  149.             {
  150.                 USBExpertFatalError(pUniversalPB->interfaceRef, kUSBInternalErr, "\pUSBUniversalModule: kConfigureInterface (ImmediateError)", myErr);
  151.             }
  152.             break;
  153.             
  154.         case kFindInterruptPipe:
  155.             pUniversalPB->pb.usbFlags = kUSBIn;
  156.             pUniversalPB->pb.usbClassType = kUSBInterrupt;
  157.             // pUniversalPB->pb.usbReference is interface ref, returns as pipe ref
  158.  
  159.             pUniversalPB->pb.usbRefcon |= kCompletionPending;
  160.             myErr = USBFindNextPipe(&pUniversalPB->pb);
  161.             if(immediateError(myErr))
  162.             {
  163.                 USBExpertFatalError(pUniversalPB->interfaceRef, kUSBInternalErr, "\pUSBUniversalModule: kFindInterruptPipe (ImmediateError)", myErr);
  164.             }
  165.             break;
  166.  
  167.         case kReadInterruptPipe:
  168.             pUniversalPB->pb.usbBuffer = (Ptr) pUniversalPB->hidReport;
  169.             pUniversalPB->pb.usbReqCount = pUniversalPB->maxPacketSize;
  170.             pUniversalPB->pb.usb.cntl.WIndex = pUniversalPB->interfaceNum;    
  171.             pUniversalPB->pb.usbFlags = 0;
  172.             
  173.             pUniversalPB->pb.usbRefcon |= kCompletionPending;
  174.             myErr = USBIntRead(&pUniversalPB->pb);
  175.             if(immediateError(myErr))
  176.             {
  177.                 USBExpertFatalError(pUniversalPB->interfaceRef, kUSBInternalErr, "\pUSBUniversalModule: Read Interrupt Pipe (ImmediateError)", myErr);
  178.             }
  179.             break;
  180.             
  181.         default:
  182.             USBExpertFatalError(pUniversalPB->interfaceRef, kUSBInternalErr, "\pUSBUniversalModule: Transaction initiated with bad refcon value", pUniversalPB->pb.usbRefcon);
  183.             pUniversalPB->pb.usbRefcon = kUndefined + kReturnFromDriver;
  184.             break;
  185.     }
  186.     
  187. // At this point the control is returned to the system.  If a USB transaction
  188. // has been initiated, then it will call the Complete procs
  189. // (below) to handle the results of the transaction.
  190. }
  191.  
  192.  
  193. void TransactionCompletionProc (USBPB *pb)
  194. {
  195. register usbUniversalPBStruct *pUniversalPB;
  196. unsigned char    * errstring;
  197. USBPipeState     pipeState;
  198. UInt32    i, j, index;
  199. UInt32    count, length;
  200. USBHIDReportDesc * currentDesc;
  201. UInt8 *    descriptorStorage;
  202.  
  203.     pUniversalPB = (usbUniversalPBStruct *)(pb);
  204.     pUniversalPB->transDepth--;
  205.     if (pUniversalPB->transDepth < 0)
  206.     {
  207.         USBExpertFatalError(pUniversalPB->interfaceRef, kUSBInternalErr, "\pUSBUniversalModule: transDepth < 0 (completion)", pUniversalPB->transDepth );
  208.     }
  209.     
  210.     if (pUniversalPB->transDepth > 1)
  211.     {
  212.         USBExpertFatalError(pUniversalPB->interfaceRef, kUSBInternalErr, "\pUSBUniversalModule: transDepth > 1 (completion)", pUniversalPB->transDepth );
  213.     }
  214.     
  215.     if(pUniversalPB->pb.usbStatus != noErr)                                                        // was there an error?
  216.     {
  217.         switch(pUniversalPB->pb.usbRefcon & kDriverStagesMask)                                    // yes, so show where the error occurred
  218.         {
  219.             case kGetHIDDesc:                      errstring = "\pUSBUniversalModule: Error during kGetHIDDesc"; break;
  220.             case kAllocHIDOwnedDescMem:            errstring = "\pUSBUniversalModule: Error during kAllocHIDOwnedDescMem"; break;
  221.             case kGet1OwnedHIDDesc:              errstring = "\pUSBUniversalModule: Error during kGet1OwnedHIDDesc"; break;
  222.             case kConfigureInterface:              errstring = "\pUSBUniversalModule: Error during kConfigureInterface"; break;
  223.             case kFindInterruptPipe:              errstring = "\pUSBUniversalModule: Error during kFindInterruptPipe"; break;
  224.             case kReadInterruptPipe:              errstring = "\pUSBUniversalModule: Error during kReadInterruptPipe"; break;
  225.             default:                              errstring = "\pUSBUniversalModule: Error occurred, but state is unknown"; break;
  226.         };
  227.         USBExpertFatalError(pUniversalPB->interfaceRef, pUniversalPB->pb.usbStatus, errstring, (pUniversalPB->pb.usbRefcon & kDriverStagesMask));
  228.         
  229.         pUniversalPB->pb.usbRefcon &= ~(kCompletionPending + kReturnFromDriver);                // set up to retry the transaction
  230.         pUniversalPB->pb.usbRefcon |= kRetryTransaction;
  231.         pUniversalPB->retryCount--;
  232.         
  233.         if ((!pUniversalPB->retryCount)    || (pUniversalPB->pb.usbStatus == kUSBAbortedError))    // have we exhausted the retries?
  234.         {                                                                                        // or received an abort?
  235.             USBExpertStatus(pUniversalPB->interfaceRef, "\pUSBUniversalModule: Pipe abort or unable to recover from error", pUniversalPB->interfaceRef);
  236.             pUniversalPB->pb.usbRefcon = kReturnFromDriver;                                        // if so, just exit.
  237.         }
  238.         else                                                                                    // if it didn't abort and there's retries left, then...
  239.         {
  240.             if (pUniversalPB->pipeRef)                                                            // check if the pipe is open.
  241.             {
  242.                 USBGetPipeStatusByReference(pUniversalPB->pipeRef, &pipeState);                    // yes, so what it's state?
  243.                 if (pipeState != kUSBActive)                                                    // if it's not active, try to clear it.  It might be stalled...
  244.                 {
  245.                     USBExpertStatus(pUniversalPB->interfaceRef, "\pUSBUniversalModule: Pipe is open and stalled, clearing stall...", pUniversalPB->interfaceRef);
  246.                     USBClearPipeStallByReference(pUniversalPB->pipeRef);
  247.                 }
  248.             }
  249.         }
  250.     }
  251.     else
  252.     {
  253.         pUniversalPB->pb.usbRefcon &= ~kRetryTransaction;
  254.         pUniversalPB->retryCount = kUniversalRetryCount;
  255.     }
  256.  
  257.     if (pUniversalPB->pb.usbRefcon & kCompletionPending)             
  258.     {                                                
  259.         pUniversalPB->pb.usbRefcon &= ~(kCompletionPending + kReturnFromDriver);
  260.         switch(pUniversalPB->pb.usbRefcon)
  261.         {
  262.             case kGetHIDDesc:
  263.                 // if we could not get anything, don't try to get the rest
  264.                 if (pUniversalPB->pb.usbActCount == 0)
  265.                 {
  266.                     pUniversalPB->pb.usbRefcon = kConfigureInterface;
  267.                     break;
  268.                 }
  269.  
  270.                 pUniversalPB->pb.usbRefcon = kAllocHIDOwnedDescMem;
  271.                 break;
  272.     
  273.             case kAllocHIDOwnedDescMem:
  274.                 pUniversalPB->hidOwnedDiscriptors = (usbHIDDescriptorInfo *) pUniversalPB->pb.usbBuffer;
  275.                 pUniversalPB->hidOwnedDescriptorsCount = 0;
  276.                 if (pUniversalPB->allocatedBufferSize != pUniversalPB->pb.usbActCount)
  277.                 {
  278.                     USBExpertStatus(pUniversalPB->interfaceRef, "\pUSBUniversalModule: could not allocate descriptor buffer", pUniversalPB->pb.usbActCount);
  279.                     pUniversalPB->pb.usbRefcon = kConfigureInterface;
  280.                     break;
  281.                 }
  282.                 
  283.                 // fill out our 'usbHIDDescriptorInfo' array
  284.                 count = pUniversalPB->hidDiscriptor.d.hidNumDescriptors;
  285.                 
  286.                 currentDesc = (USBHIDReportDesc *) &pUniversalPB->hidDiscriptor.d.hidDescriptorType;
  287.                 descriptorStorage = (UInt8 *) pUniversalPB->hidOwnedDiscriptors;
  288.                 descriptorStorage += count * sizeof (usbHIDDescriptorInfo);    // inital part for the array
  289.                 
  290.                 for (i = 0; i < count; i++)
  291.                 {
  292.                     length = (currentDesc->hidDescriptorLengthHi << 8) + currentDesc->hidDescriptorLengthLo;
  293.  
  294.                     pUniversalPB->hidOwnedDiscriptors[i].type = currentDesc->hidDescriptorType;
  295.                     pUniversalPB->hidOwnedDiscriptors[i].length = length;
  296.                     pUniversalPB->hidOwnedDiscriptors[i].descriptor = descriptorStorage;
  297.                     
  298.                     index = 0;
  299.                     for (j = 0; j < i; j++)
  300.                         if (pUniversalPB->hidOwnedDiscriptors[j].type == currentDesc->hidDescriptorType)
  301.                             index++;
  302.                     
  303.                     pUniversalPB->hidOwnedDiscriptors[i].typeIndex = index;
  304.  
  305.                     currentDesc = (USBHIDReportDesc *) (((UInt8 *) currentDesc) + 3);    // make _sure_ we add 3 bytes not 4 regardless of struct alignment
  306.                     descriptorStorage += length;
  307.                 }
  308.                 
  309.                 // next, we'll get the 1st owned descriptor (by 1.0 spec there will _always_ be at least 1)
  310.                 pUniversalPB->pb.usbRefcon = kGet1OwnedHIDDesc;
  311.                 break;
  312.     
  313.             case kGet1OwnedHIDDesc:
  314.                 if (pUniversalPB->hidOwnedDiscriptors[pUniversalPB->hidOwnedDescriptorsCount].length != pUniversalPB->pb.usbActCount)
  315.                     USBExpertStatus(pUniversalPB->interfaceRef, "\pUSBUniversalModule: get owned HID descriptor wrong size", pUniversalPB->pb.usbActCount);
  316.                 
  317.                 // we successfully got it, so increment
  318.                 pUniversalPB->hidOwnedDescriptorsCount++;
  319.                 
  320.                 // now get more if we need to, otherwise move on
  321.                 if (pUniversalPB->hidOwnedDescriptorsCount < pUniversalPB->hidDiscriptor.d.hidNumDescriptors)
  322.                     pUniversalPB->pb.usbRefcon = kGet1OwnedHIDDesc;
  323.                 else // we're done
  324.                     pUniversalPB->pb.usbRefcon = kConfigureInterface;
  325.                 break;
  326.  
  327.             case kConfigureInterface:
  328.                 pUniversalPB->numPipes = pUniversalPB->pb.usbOther;
  329.  
  330.                 pUniversalPB->pb.usbRefcon = kFindInterruptPipe;
  331.                 break;
  332.                 
  333.             case kFindInterruptPipe:
  334.                 pUniversalPB->pipeRef = pUniversalPB->pb.usbReference;
  335.                 pUniversalPB->maxPacketSize = pUniversalPB->pb.usb.cntl.WValue;
  336.  
  337.                 pUniversalPB->pb.usbRefcon = kReadInterruptPipe;
  338.                 break;
  339.                 
  340.             case kReadInterruptPipe:
  341.                 NotifyRegisteredHIDUser(pUniversalPB->hidReport);
  342.  
  343.                 pUniversalPB->pb.usbRefcon = kReadInterruptPipe;
  344.                 break;
  345.         }
  346.     }
  347.  
  348.     if (!(pUniversalPB->pb.usbRefcon & kReturnFromDriver))
  349.         UniversalModuleInitiateTransaction(pb);
  350. }
  351.  
  352.  
  353. void DriverEntry(USBDeviceRef device, USBDeviceDescriptorPtr pDeviceDescriptor)
  354. {
  355. #pragma unused (device)
  356. #pragma unused (pDeviceDescriptor)
  357.  
  358. static Boolean beenThereDoneThat = false;
  359.  
  360.     return;
  361. }
  362.  
  363. void InterfaceEntry(UInt32 interfaceNum, USBInterfaceDescriptorPtr pInterfaceDescriptor, USBDeviceDescriptorPtr pDeviceDescriptor, USBInterfaceRef interfaceRef)
  364. {
  365. static Boolean beenThereDoneThat = false;
  366.  
  367.     if(beenThereDoneThat)
  368.     {
  369.         USBExpertFatalError(interfaceRef, kUSBInternalErr, "\pUSBUniversalModule is not reentrant", 0);
  370.         return;
  371.     }
  372.     beenThereDoneThat = true;
  373.     
  374.     // store off parameters
  375.     myUniversalPB.interfaceNum = interfaceNum;
  376.     myUniversalPB.interfaceDescriptor = *pInterfaceDescriptor;                
  377.     myUniversalPB.deviceDescriptor = *pDeviceDescriptor;                
  378.     myUniversalPB.interfaceRef = interfaceRef;        
  379.  
  380.     myUniversalPB.transDepth = 0;                            
  381.     myUniversalPB.retryCount = kUniversalRetryCount;
  382.       
  383.     myUniversalPB.pClientInterruptRoutine = nil;
  384.     myUniversalPB.clientRefCon = 0;        
  385.  
  386.     myUniversalPB.pipeRef = nil;        
  387.  
  388.     SetParamBlock(interfaceRef, &myUniversalPB.pb);
  389.     
  390.     USBExpertStatus(myUniversalPB.interfaceRef, "\pUSBUniversalModule: Driver loaded and starting up...", myUniversalPB.interfaceRef);
  391.     
  392.     myUniversalPB.pb.usbRefcon = kGetHIDDesc;
  393.     UniversalModuleInitiateTransaction(&myUniversalPB.pb);
  394. }
  395.  
  396. void    InterfaceExit(USBInterfaceRef interfaceRef, USBInterfaceDescriptorPtr pInterfaceDescriptor)
  397. {
  398. #pragma unused (pInterfaceDescriptor)
  399.  
  400. OSStatus myErr;
  401.  
  402.     USBExpertStatus(interfaceRef, "\pUSBHIDUniversalModule: Finalize", interfaceRef);
  403.     
  404.     if (myUniversalPB.pipeRef != 0)
  405.     {
  406.         USBExpertStatus(interfaceRef, "\pUSBHIDMouseModule: Aborting interrupt pipe", interfaceRef);
  407.         USBAbortPipeByReference(myUniversalPB.pipeRef);
  408.         myUniversalPB.pipeRef = 0;
  409.     }
  410.  
  411.     if (myUniversalPB.hidOwnedDiscriptors != nil)
  412.     {
  413.         myUniversalPB.pb.usbReference = interfaceRef;
  414.         myUniversalPB.pb.pbVersion = kUSBCurrentPBVersion;
  415.         myUniversalPB.pb.usbFlags = 0;
  416.         myUniversalPB.pb.usbRefcon = 0;             
  417.         myUniversalPB.pb.usbBuffer = myUniversalPB.hidOwnedDiscriptors;        
  418.         myUniversalPB.pb.usbCompletion = kUSBNoCallBack;
  419.         
  420.         myErr = USBDeallocMem(&myUniversalPB.pb);
  421.         myUniversalPB.hidOwnedDiscriptors = nil;
  422.     }
  423. }
  424.  
  425.